/*
 *  Copyright (C) 2004 Cidero, Inc.
 *
 *  Permission is hereby granted to any person obtaining a copy of 
 *  this software to use, copy, modify, merge, publish, and distribute
 *  the software for any non-commercial purpose, subject to the
 *  following conditions:
 *  
 *  The above copyright notice and this permission notice shall be included
 *  in all copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 
 *  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 
 *  THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *  LIABILITY IN CONNECTION WITH THE SOFTWARE.
 * 
 *  File: $RCSfile: CDSPlaylistContainer.java,v $
 *
 */

package com.cidero.upnp;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.logging.Logger;

import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import org.cybergarage.xml.XML;

/**
 *
 *  Derived class of CDSContainer used to represent a playable set of resources
 *  Most commonly, children of this object will be CDSMusicTrack or 
 *  CDSImageItem objects. The object may hava a <res> element (typically 
 *  an M3U playlist file URL) authored outside the ContentDirectory
 *
 *  Notes:
 *
 *  This object should be used preferentially over CDSPlaylistItem,
 *  which has been basically deprecated in the Intel NMPR 2.0 requirements
 *
 */
public class CDSPlaylistContainer extends CDSContainer
{
  private static Logger logger = Logger.getLogger("com.cidero.upnp");

  static String upnpClass = "object.container.playlistContainer";

  // UPnP namespace fields
  String  artist;                          // Not required
  String  genre;                           // Not required
  String  longDescription;                 // Not required
  String  producer;                        // Not required
  String  storageMedium;                   // Not required

  // Dublin Core namespace fields
  String  description;                     // Not required
  String  contributor;                     // Not required
  String  date;                            // Not required 
  String  language;                        // Not required
  String  rights;                          // Not required


  public CDSPlaylistContainer()
  {
  }

  public CDSPlaylistContainer( Node node )
  {
    super( node );

    NodeList children = node.getChildNodes();

    for( int n = 0 ; n < children.getLength() ; n++ )
    {
      String nodeName = children.item(n).getNodeName();
      //      System.out.println( "Node is: " + nodeName );
      
      if (nodeName.equals("upnp:artist"))
        artist = CDS.getSingleTextNodeValue(children.item(n));
      else if( nodeName.equals("upnp:genre") )
        genre = CDS.getSingleTextNodeValue( children.item(n) );
      else if( nodeName.equals("upnp:longDescription") )
        longDescription = CDS.getSingleTextNodeValue( children.item(n) );
      else if( nodeName.equals("upnp:producer") )
        producer = CDS.getSingleTextNodeValue( children.item(n) );
      else if (nodeName.equals("upnp:storageMedium"))
        storageMedium = CDS.getSingleTextNodeValue(children.item(n));

      else if( nodeName.equals("dc:contributor") )
        contributor = CDS.getSingleTextNodeValue( children.item(n) );
      else if( nodeName.equals("dc:description") )
        description = CDS.getSingleTextNodeValue( children.item(n) );
      else if (nodeName.equals("dc:date")) 
        date = CDS.getSingleTextNodeValue(children.item(n));
      else if( nodeName.equals("dc:language") )
        language = CDS.getSingleTextNodeValue( children.item(n) );
      else if( nodeName.equals("dc:rights") )
        rights = CDS.getSingleTextNodeValue( children.item(n) );
    }
  }

  /**
   * Browse children using a playlist resource (most commonly an M3U file)
   *
   * @return  Returns list of CDS objects (most commonly musicTracks)
   *
   * Notes: Only M3U resources are currently supported 
   */
  public CDSObjectList browseChildrenUsingHTTP() 
  {
    CDSResource resource = getResource(0);
    if( resource == null )
      return null;
    
    // Accept a resource as an M3U file if it has the matching protocol
    if( ! resource.getProtocolInfo().equals("http-get:*:audio/mpegurl:*") )
    {
      logger.fine("browse failed - playlist has no M3U resource - protocol = "
                  + resource.getProtocolInfo() );
      return null;
    }

    logger.fine( "browsing playlist resource: " + resource.getName() );

    try 
    {
      M3UPlaylist m3uPlaylist =
        new M3UPlaylist( new URL( resource.getName() ) ); 

      logger.fine("Playlist items = " + m3uPlaylist.size() );
      if( m3uPlaylist.size() == 0 )
        return null;
      
      return m3uPlaylist.getObjectList();
      
    }
    catch( MalformedURLException e )
    {
      logger.fine("Malformed Playlist URL: " + resource.getName() );
      return null;
    }
    catch( IOException e )
    {
      logger.fine("IOException accessing playlist: " + resource.getName() );
      return null;
    }
    catch( PlaylistException e )
    {
      logger.warning("Playlist error: " + e);
      return null;
    }
  }

  public void setArtist(String artist) { this.artist = artist; }
  public String getArtist() { return artist; }

  public void setGenre( String genre ) { this.genre = genre; }
  public String getGenre() { return genre; }

  public void setStorageMedium(String storageMedium) {
    this.storageMedium = storageMedium;
  }
  public String getStorageMedium() { return storageMedium; }

  public void setLongDescription( String description ) {
    this.longDescription = description;
  }
  public String getLongDescription() { return longDescription; }

  public void setProducer(String producer) {
    this.producer = producer;
  }
  public String getProducer() { return producer; }

  public void setDescription( String description ) {
    this.description = description;
  }
  public String getDescription() { return description; }

  public void setContributor( String contributor ) {
    this.contributor = contributor;
  }
  public String getContributor() { return contributor; }

  public void setDate(String date) { this.date = date; }
  public String getDate() { return date; }

  public void setLanguage( String language ) { this.language = language; }
  public String getLanguage() { return language; }

  public void setRights( String rights ) { this.rights = rights; }
  public String getRights() { return rights; }


  /**
   *  Get object class
   *
   *  @return  UPNP class string
   */
  public String getUPNPClass() { return upnpClass; }

  public String attributesToXML( CDSFilter filter )
  {
    // No extra attributes for this class (just elements)
    return super.attributesToXML( filter );  
  }

  public String elementsToXML( CDSFilter filter )
  {
    // Need to build element string starting with elements in base classes
    StringBuffer buf = new StringBuffer();
    
    buf.append( super.elementsToXML( filter ) );

    if( (artist != null) && filter.propertyEnabled("upnp:artist") )
      XML.appendXMLElementLine( buf, "  ", "upnp:artist", artist );

    if( (genre != null) && filter.propertyEnabled( "upnp:genre" ) )
      XML.appendXMLElementLine( buf, "  ", "upnp:genre", genre );
    
    if( (longDescription != null) &&
        filter.propertyEnabled( "upnp:longDescription" ) )
      XML.appendXMLElementLine( buf, "  ", "upnp:longDescription",
                                longDescription );

    if( (producer != null) && filter.propertyEnabled( "upnp:producer" ) )
      XML.appendXMLElementLine( buf, "  ", "upnp:producer", producer );
    
    if( (storageMedium != null) &&
        filter.propertyEnabled( "upnp:storageMedium" ) )
      XML.appendXMLElementLine( buf, "  ",
                                "upnp:storageMedium", storageMedium );

    if( (description != null) && filter.propertyEnabled( "dc:description" ) )
      XML.appendXMLElementLine( buf, "  ", "dc:description", description );

    if( (contributor != null) && filter.propertyEnabled("dc:contributor") )
      XML.appendXMLElementLine( buf, "  ", "dc:contributor", contributor );

    if( (date != null) && filter.propertyEnabled("dc:date") )
      XML.appendXMLElementLine( buf, "  ", "dc:date", date );

    if( (language != null) && filter.propertyEnabled( "dc:language" ) )
      XML.appendXMLElementLine( buf, "  ", "dc:language", language );

    if( (rights != null) && filter.propertyEnabled( "dc:rights" ) )
      XML.appendXMLElementLine( buf, "  ", "dc:rights", rights );

    return buf.toString();
  }

  /**
   * Simple test program
   */
  public static void main( String[] args )
  {
    CDSPlaylistContainer playlist = new CDSPlaylistContainer();

    CDSResource resource = new CDSResource();
    if( args.length < 1 )
    {
      System.out.println("Usage: java CDSPlaylistContainer <M3U URL>");
      System.exit(-1);
    }
    
    resource.setName( args[0] );
    resource.setProtocolInfo( "http-get:*:audio/mpegurl:*" );
    resource.setDuration( "03:00" );
    resource.setSize( 5000000 );
    
    playlist.addResource( resource );
    
    CDSObjectList objList = playlist.browseChildrenUsingHTTP();

    System.out.println( objList.toString() );
  }

}
